<?php

namespace App\Services\Stats\Game\Elasticsearch;

use App\Core\Traits\Numeral;
use App\Exports\Stats\Game\GameUsdExport;
use App\Services\Service;
use App\Services\Traits\DatabaseElasticsearch;
use App\Models\Elasticsearch\Settlement\Info as SettlementInfo;

class GameService extends Service
{
	use DatabaseElasticsearch, Numeral;

	/**
	 * 获取游戏统计USD
	 *
	 * @param \Illuminate\Http\Request $request
	 * @return array[]|int[]|array[]
	 */
	public function getList($request, $export = false)
	{
		$params = ['body' => ['size' => 0]];

		// 筛选【状态】
		$this->makeWhere($params, 'status', SettlementInfo::STATUS_NORMAL);
		// 筛选【类型】
		$this->makeWhere($params, 'player_type', SettlementInfo::PLAYER_TYPE);
		// 筛选【平台】
		$this->makeWhereParamOrg($request, $params);
		// 筛选【平台】【排除】
		$this->makeWhereParamNot($request, 'plat_code_exclude', $params, 'plat_code');
		// 筛选【时间】
		$this->makeWhereParamDatetime($request, $params, 'end_time', 'datetime', SettlementInfo::INDEX_NAME);
		// 筛选【游戏】
		$this->makeWhereParam($request, 'game_id', $params);
		$this->makeWhereParam($request, 'currency', $params);
		// 筛选【游戏】【排除】
		$this->makeWhereParamNot($request, 'game_id_exclude', $params, 'game_id');
		$this->makeWhereParamNot($request, 'currency_exclude', $params, 'currency');

		// 列表数据
		$this->makeGroupAggs($request, $params, 'sum', ['bet_base', 'bet_num', 'gain_player', 'usd.bet_base', 'usd.bet_num', 'usd.gain_player'],
		['currency', 'game_id']);
		$params['body']['aggs']['group']['aggs'] = array_merge($params['body']['aggs']['group']['aggs'], $this->makeDistinct('uid'));

		//排序
		$order_column = $request->input('order_column', 'bet_base');
		switch ($order_column){
			case "game_id":
				$order_column = 'bet_base';
				break;
			case "player_count":
				$order_column = 'distinct_uid';
				break;
			case "doc_count":
				$order_column = '_count';
				break;
		}
		$this->makeAggsOrderParam($request, $params, $order_column);

		$curParams = $params;
		$this->makeGroupAggs($request, $curParams, 'sum', ['bet_base', 'bet_num', 'gain_player'], ['currency']);
		$curParams['body']['aggs']['group']['aggs'] = array_merge($curParams['body']['aggs']['group']['aggs'], $this->makeDistinct('uid'));
		$this->makeAggs($curParams, 'sum', ['usd.bet_base', 'usd.bet_num', 'usd.gain_player']);
		$curParams['body']['aggs'] = array_merge($curParams['body']['aggs'], $this->makeDistinct('uid'));
		$curStat = SettlementInfo::search($curParams);

		$aggStat = SettlementInfo::search($params);

		// 数据条数
		$total = isset($aggStat['aggregations']) ? count($aggStat['aggregations']['group']['buckets']) : 0;


		$this->makeAggs($params, 'sum', ['bet_base', 'bet_num', 'gain_player', 'usd.bet_base', 'usd.bet_num', 'usd.gain_player']);
		$params['body']['aggs'] = array_merge($params['body']['aggs'], $this->makeDistinct('uid'));

		//分页
		$this->makeAggsPaginationParam($request, $params);

		// 查询数据
		$results = SettlementInfo::search($params);
		$data = $this->makeList($results['aggregations'] ?? null);


		// 统计数据
		$stats = $this->makeStats($curStat['aggregations'] ?? null);

		return [
			$data,
			$total,
			$stats,
		];
	}

	private function makeList($aggs)
	{
		if (is_null($aggs)) {
			return [];
		}

		$data = collect($aggs['group']['buckets'])->map(function ($item) {
			return [
				'bet_base' => $item['bet_base']['value'],
				'bet_num' => $item['bet_num']['value'],
				'currency' => $item['key']['currency'],
				'game_id' => $item['key']['game_id'],
				'doc_count' => $item['doc_count'],
				'gain_player' => $item['gain_player']['value'],
				'player_count' => $item['distinct_uid']['value'],
				'usd_amount' => -$item['usd.gain_player']['value'],
				'usd_bet_base' => $item['usd.bet_base']['value'],
				'usd_bet_num' => $item['usd.bet_num']['value'],
				'usd_gain_player' => $item['usd.gain_player']['value'],
				'rtp' => $this->makeRtp($item['bet_num']['value'], $item['gain_player']['value']),
			];
		});
		return $data;
	}

	/**
	 * 获取游戏统计USD
	 *46	46	9	0.9.46	接入文档	book	/platform/doc	platform.doc		1655429936	1655429936
	 * @param \Illuminate\Http\Request $request
	 * @return array[]|int[]|array[]
	 */
	public function getUsd($request, $export = false)
	{
		$params = ['body' => ['size' => 0]];

		// 筛选【状态】
		$this->makeWhere($params, 'status', SettlementInfo::STATUS_NORMAL);
		// 筛选【类型】
		$this->makeWhere($params, 'player_type', SettlementInfo::PLAYER_TYPE);
		// 筛选【平台】
		$this->makeWhereParamOrg($request, $params);
		// 筛选【平台】【排除】
		$this->makeWhereParamNot($request, 'plat_code_exclude', $params, 'plat_code');
		// 筛选【时间】
		$this->makeWhereParamDatetime($request, $params, 'end_time', 'datetime', SettlementInfo::INDEX_NAME);
		// 筛选【游戏】
		$this->makeWhereParam($request, 'game_id', $params);
		// 筛选【游戏】【排除】
		$this->makeWhereParamNot($request, 'game_id_exclude', $params, 'game_id');

		// 统计数据

		$this->makeGroupAggs($request, $params, 'sum', ['bet_base', 'bet_num', 'gain_player', 'usd.bet_base', 'usd.bet_num', 'usd.gain_player'], ['game_id'], '', 'datetime', '_');
		$params['body']['aggs']['group']['aggs'] = array_merge($params['body']['aggs']['group']['aggs'], $this->makeDistinct('uid'));

		//排序
		$order_column = $request->input('order_column', 'bet_base');
		switch ($order_column){
			case "player_count":
				$order_column = 'distinct_uid';
				break;
			case "doc_count":
				$order_column = '_count';
				break;
			case "bet_num":
				$order_column = 'usd_bet_num';
				break;
			case "bet_base":
				$order_column = 'usd_bet_base';
				break;
			case "gain_player":
				$order_column = 'usd_gain_player';
				break;
		}
		$this->makeAggsOrderParam($request, $params, $order_column);

		$this->makeAggs($params, 'sum', ['bet_base', 'bet_num', 'gain_player', 'usd.bet_base', 'usd.bet_num', 'usd.gain_player']);
		$params['body']['aggs'] = array_merge($params['body']['aggs'], $this->makeDistinct('uid'));

		// 查询数据
		$results = SettlementInfo::search($params);

		// 统计数据
		$stats = $this->makeStatsUsd($results['aggregations'] ?? null);

		return [
			$stats['data'],
			$stats['usd'],
		];
	}

	private function makeStatsUsd($aggs)
	{
		if (is_null($aggs)) {
			return ['usd' => new \stdClass(), 'data' => []];
		}

		// USD【合计】
		$usd = [
			'gain_player' => $aggs['usd.gain_player']['value'],
			'amount' => -$aggs['usd.gain_player']['value'],
			'bet_base' => $aggs['usd.bet_base']['value'],
			'bet_num' => $aggs['usd.bet_num']['value'],
			'player_count' => $aggs['distinct_uid']['value'],
			'doc_count' => 0,
		];
		// USD【RTP】
		$usd['rtp'] = $this->makeRtp($usd['bet_num'], $usd['gain_player']);

		// 分游戏【合计】
		$data = collect($aggs['group']['buckets'])->map(function ($item)use(&$usd) {
			$usd['doc_count'] += $item['doc_count'];

			return [
				'bet_base' => $item['usd_bet_base']['value'],
				'bet_num' => $item['usd_bet_num']['value'],
				'game_id' => $item['key']['game_id'],
				'doc_count' => $item['doc_count'],
				'gain_player' => $item['usd_gain_player']['value'],
				'amount' => -$item['usd_gain_player']['value'],
				'player_count' => $item['distinct_uid']['value'],
			];
		});
		// 分币种【RTP】
		$data->transform(function ($item) {
			return $item + ['rtp' => $this->makeRtp($item['bet_num'], $item['gain_player'])];
		});

		return [
			'usd' => $usd,
			'data' => $data,
		];
	}

	private function makeStats($aggs)
	{
		if (is_null($aggs)) {
			return [
				'usd' => [],
				'sts' => [],
			];
		}
		// USD【合计】
		$usd = [
			'gain_player' => $aggs['usd.gain_player']['value'],
			'amount' => -$aggs['usd.gain_player']['value'],
			'bet_base' => $aggs['usd.bet_base']['value'],
			'bet_num' => $aggs['usd.bet_num']['value'],
			'player_count' => $aggs['distinct_uid']['value'],
			'doc_count' => 0,
		];
		// USD【RTP】
		$usd['rtp'] = $this->makeRtp($usd['bet_num'], $usd['gain_player']);

		$currency = collect($aggs['group']['buckets'])->map(function ($item)use(&$usd) {
			$usd['doc_count'] += $item['doc_count'];

			return [
				'bet_base' => $item['bet_base']['value'],
				'bet_num' => $item['bet_num']['value'],
				'currency' => $item['key']['currency'],
				'doc_count' => $item['doc_count'],
				'gain_player' => $item['gain_player']['value'],
				'player_count' => $item['distinct_uid']['value'],
				'amount' => -$item['gain_player']['value'],
				'rtp' => $this->makeRtp($item['bet_num']['value'], $item['gain_player']['value']),
			];
		});
		return [
			'usd' => $usd,
			'sts' => $currency,
		];
	}
}
